﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using MugenInjection.Activators;
using MugenInjection.Delegates;
using MugenInjection.Exceptions;
using MugenInjection.Infrastructure;
using MugenInjection.Interface;
using MugenInjection.Parameters;
using MugenInjection.Scope;
using MugenInjection.Syntax;
using MugenInjection.Syntax.Constant;
using MugenInjection.Syntax.Method;
using MugenInjection.Syntax.Type;
#if !NOEXPRESSION
using System.Linq.Expressions;
#endif

namespace MugenInjection.Bindings.Builders
{
    internal class BindingBuilder<T1, T2, T3, T4> : IBindingSyntax,
                                                    IGenericBindingSyntax<T1>,
                                                    IGenericBindingSyntax<T1, T2>,
                                                    IGenericBindingSyntax<T1, T2, T3>,
                                                    IGenericBindingSyntax<T1, T2, T3, T4>,
                                                    IConstantCallbackObjectPriorityWhenSyntax<T1>,
                                                    IConstantCallbackObjectPrioritySyntax<T1>,
                                                    IConstantObjectSyntax<T1>,
                                                    IConstantObjectPriorityWhenSyntax,
                                                    IConstantObjectPrioritySyntax,
                                                    IConstantObjectSyntax,
                                                    IMethodCallbackObjectUseWithSyntax<T1>,
                                                    IMethodCallbackObjectUseWithSyntax,
                                                    IMethodCallbackObjectPriorityUseWithSyntax<T1>,
                                                    IMethodCallbackObjectPriorityUseWithSyntax,
                                                    IMethodCallbackObjectPriorityScopeUseWithSyntax<T1>,
                                                    IMethodCallbackObjectPriorityScopeUseWithSyntax,
                                                    IMethodCallbackObjectPriorityScopeUseWhenWithSyntax<T1>,
                                                    IMethodCallbackObjectPriorityScopeUseWhenWithSyntax,
                                                    ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<T1>,
                                                    ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax,
                                                    ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax,
                                                    ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax<T1>,
                                                    ITypeCallbackConstructorObjectPriorityUseWithSyntax<T1>,
                                                    ITypeCallbackConstructorObjectPriorityUseWithSyntax,
                                                    ITypeCallbackObjectPriorityUseWithSyntax<T1>,
                                                    ITypeCallbackObjectPriorityUseWithSyntax,
                                                    ITypeCallbackObjectUseWithSyntax<T1>,
                                                    ITypeCallbackObjectUseWithSyntax
    {
        #region Fields

        private const string IsBuildingKey = "_IsBuildingKey_";
        private const string IsBuildedKey = "_IsBuildedKey_";
        private const string LockerKey = "_LockerKey_";
        private BindingBuilderConfigurator _configurator;

        #endregion

        #region Constructor

        private BindingBuilder()
        {
        }

        public BindingBuilder(IList<Type> services, IInjector injector)
            : this(services, injector, false)
        {
        }

        public BindingBuilder(IList<Type> services, IInjector injector, bool addBindingToInjectorToInjector)
        {
            Validate.ArgumentNotNullAndNonZeroLength(services, "services");
            Validate.ArgumentNotNull(injector, "injector");
            Validate.EnsureIsHaveCommonParent(services);
            _configurator = new BindingBuilderConfigurator(this, addBindingToInjectorToInjector);
            if (InjectorUtilsInternal.RemoveDuplicate(ref services))
                throw new ArgumentException("Duplication of service types.", "services");
            Injector = injector;
            Services = services;
            Locker = new object();
            IsBuilding = false;
            IsBuilded = false;
        }

        #endregion

        #region Properties

        private object Locker
        {
            get { return Settings.Get<object>(LockerKey); }
            set { Settings[LockerKey] = value; }
        }

        private bool IsBuilding
        {
            get { return Settings.Get<bool>(IsBuildingKey); }
            set { Settings[IsBuildingKey] = value; }
        }

        private bool IsBuilded
        {
            get { return Settings.Get<bool>(IsBuildedKey); }
            set { Settings[IsBuildedKey] = value; }
        }

        #endregion

        #region Methods

        private BindingBuilder<TType, object, object, object> Copy<TType>()
        {
            var bindingBuilder = new BindingBuilder<TType, object, object, object>
                {
                    Injector = Injector,
                    Services = Services,
                    _configurator = _configurator
                };
            return bindingBuilder;
        }

#if !NOEXPRESSION
        private void SetToExpression<TTypeTo>(Expression<Func<ResolveContext, TTypeTo>> expression,
                                              params IInjectionParameter[] bindParams)
        {
            Validate.ArgumentNotNull(expression, "expression");
            Validate.ArgumentNotNull(bindParams, "bindParams");
            ConstructorInfo constructorInfo;
            List<IInjectionParameter> parameters = InjectorUtilsInternal.ParseNewExpression(expression,
                                                                                            out constructorInfo);
            To(constructorInfo.DeclaringType);
            _configurator.Constructor = constructorInfo;
            if (bindParams != null)
                parameters.AddRange(bindParams);
            foreach (IInjectionParameter injectionParameter in parameters)
                _configurator.AddParameter(injectionParameter);
        }
#endif

        /// <summary>
        /// Builds the current <see cref="IBindingBuilder"/>.
        /// </summary>
        /// <returns>The builded <see cref="BindingBase"/>.</returns>
        private BindingBase BuildBinding()
        {
            if (!_configurator.BuildBindingType.HasValue)
                throw new InvalidBindingException(
                    "The binding is not initialized, it indicates that you forgot to specify the type of the object or when create a binding error has occurred.");
            BindingBuilderConfigurator.BindingType bindingType = _configurator.BuildBindingType.Value;
            var dependencyLifecycle = _configurator.GetDependencyLifecycle();
            CanResolveBindingDelegate condition = _configurator.GetCanResolveCondition();
            switch (bindingType)
            {
                case BindingBuilderConfigurator.BindingType.Constant:
                    return new ConstantBinding(_configurator.ConstValue, Services, _configurator.InjectionParameters,
                                               condition);
                case BindingBuilderConfigurator.BindingType.Method:
                    return new MethodBinding(_configurator.MethodValue, _configurator.GetActivator(true), Services,
                                             dependencyLifecycle,
                                             _configurator.InjectionParameters, condition);
                case BindingBuilderConfigurator.BindingType.CustomBinding:
                    return new CustomBinding(_configurator.CustomBindingValue, _configurator.GetActivator(true),
                                             Services, dependencyLifecycle,
                                             _configurator.InjectionParameters, condition);
                case BindingBuilderConfigurator.BindingType.Type:
                    return new TypeBinding(_configurator.TypeToValue, _configurator.GetActivator(false),
                                           _configurator.GetResolver(), Services,
                                           dependencyLifecycle, _configurator.InjectionParameters, condition, false);
                default:
                    throw Validate.EnumOutOfRange(bindingType, "bindingType");
            }
        }

        private IBinding BuildInternal()
        {
            if (IsBuilded)
                throw new ObjectDisposedException("The binding builder support only one access to binding.");
            IsBuilded = true;
            BindingBase buildedBinding = BuildBinding();
            _configurator.AddOptionalSetting(buildedBinding);
            return buildedBinding;
        }

        #endregion

        #region Implementation of IBindingBuilder

        /// <summary>
        /// Gets the <see cref="IInjector"/> that owns the <see cref="IBindingBuilder"/>.
        /// </summary>
        public IInjector Injector { get; private set; }

        /// <summary>
        /// Gets the specified service types. 
        /// </summary>
        public IList<Type> Services { get; private set; }

        /// <summary>
        /// Gets the settings for the current <see cref="IBindingBuilder"/>.
        /// </summary>
        public ISettings Settings
        {
            get { return _configurator.Settings; }
        }

        /// <summary>
        ///     Indicates that the binding builder is configuring.
        /// </summary>
        public bool IsConfiguring
        {
            get { return _configurator.IsConfiguring; }
        }

        /// <summary>
        ///     Occurs before build the current IBindingBuilder.
        /// </summary>
        public event BindingBuildingDelegate Building
        {
            add { _configurator.AddBuildingEvent(value); }
            remove { _configurator.RemoveBuildingEvent(value); }
        }

        /// <summary>
        ///     Occurs after build current IBindingBuilder.
        /// </summary>
        public event BindingBuildedDelegate Builded
        {
            add { _configurator.AddBuildedEvent(value); }
            remove { _configurator.RemoveBuildedEvent(value); }
        }

        /// <summary>
        /// Builds the current <see cref="IBindingBuilder"/>.
        /// </summary>
        /// <returns>The builded <see cref="IBinding"/>.</returns>
        public IBinding Build()
        {
            lock (Locker)
            {
                if (IsBuilding)
                    return BuildInternal();
                IsBuilding = true;
            }
            return _configurator.Build();
        }

        #endregion

        #region Implementation of ICommonBindingSyntax

        /// <summary>
        /// Indicates that the service should be bound to the specified type.
        /// </summary>
        /// <param name="typeTo">The specified <see cref="System.Type"/>.</param>
        /// <returns></returns>
        public ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax To(Type typeTo)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(typeTo, "typeTo");
                _configurator.CheckToBinding(typeTo);
                _configurator.BuildBindingType = BindingBuilderConfigurator.BindingType.Type;
                _configurator.TypeToValue = typeTo;
                return this;
            }
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified custom binding.
        /// </summary>
        /// <param name="customBinding">The specified <see cref="IBinding"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityScopeUseWhenWithSyntax ToCustomBinding(IBinding customBinding)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(customBinding, "customBinding");
                _configurator.CheckToBinding();
                _configurator.BuildBindingType = BindingBuilderConfigurator.BindingType.CustomBinding;
                _configurator.CustomBindingValue = customBinding;
                return this;
            }
        }

        #endregion

        #region Implementation of IBindingSyntax

        /// <summary>
        /// Indicates that the service should be self-bound.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax ToSelf()
        {
            if (Services == null || Services.Count != 1)
                throw new NotSupportedException("The self-bindable binding is supported only if you have a one service.");
            return To(Services[0]);
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified method.
        /// </summary>
        /// <param name="methodBindingDelegate">The specified <see cref="MethodBindingDelegate"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityScopeUseWhenWithSyntax ToMethod(MethodBindingDelegate methodBindingDelegate)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(methodBindingDelegate, "methodBindingDelegate");
                _configurator.CheckToBinding();
                _configurator.BuildBindingType = BindingBuilderConfigurator.BindingType.Method;
                _configurator.MethodValue = methodBindingDelegate;
                return this;
            }
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constant value.
        /// </summary>
        /// <param name="constValue">The specified constant value.</param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectPriorityWhenSyntax ToConstant(object constValue)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(constValue, "constValue");
                _configurator.CheckToBinding(constValue);
                _configurator.BuildBindingType = BindingBuilderConfigurator.BindingType.Constant;
                _configurator.ConstValue = constValue;
                return this;
            }
        }

        #endregion

        #region Implementation of IGenericBindingSyntax<T>

        /// <summary>
        /// Indicates that the service should be self-bound.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<T1> IGenericBindingSyntax<T1>.ToSelf()
        {
            To(typeof(T1));
            return this;
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified type <see cref="T1"/>.
        /// </summary>
        /// <typeparam name="TTypeTo">The specified <see cref="System.Type"/>.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1>.To<TTypeTo>()
        {
            To(typeof(TTypeTo));
            return Copy<TTypeTo>();
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified method.
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <typeparam name="TTypeTo"> </typeparam>
        /// <param name="methodBindingDelegate">The specified <see cref="MethodBindingDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1>.ToMethod<TTypeTo>(
            MethodBindingDelegate<TTypeTo> methodBindingDelegate)
        {
            ToMethod(context => methodBindingDelegate(context));
            return Copy<TTypeTo>();
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constant value.
        /// </summary>
        /// <param name="constValue">The specified constant value.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPriorityWhenSyntax<TTypeTo> IGenericBindingSyntax<T1>.ToConstant<TTypeTo>(
            TTypeTo constValue)
        {
            ToConstant(constValue);
            return Copy<TTypeTo>();
        }

#if !NOEXPRESSION
        /// <summary>
        /// Adds a constructor argument for the specified argument expression.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1>.To<TTypeTo>(
            Expression<Func<ResolveContext, TTypeTo>> expression, params IInjectionParameter[] bindParams)
        {
            SetToExpression(expression, bindParams);
            return Copy<TTypeTo>();
        }
#endif

        #endregion

        #region Implementation of IGenericBindingSyntax<T1,T2>

        /// <summary>
        /// Indicates that the service should be bound to the specified types.
        /// </summary>
        /// <typeparam name="TTypeTo">The specified <see cref="System.Type"/>.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1, T2>.To<TTypeTo>()
        {
            To(typeof(TTypeTo));
            return Copy<TTypeTo>();
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified method.
        /// </summary>
        /// <typeparam name="TTypeTo"></typeparam>
        /// <param name="methodBindingDelegate">The specified <see cref="MethodBindingDelegate{TTypeTo}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1, T2>.ToMethod<TTypeTo>(
            MethodBindingDelegate<TTypeTo> methodBindingDelegate)
        {
            ToMethod(context => methodBindingDelegate(context));
            return Copy<TTypeTo>();
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constant value.
        /// </summary>
        /// <param name="constValue">The specified constant value.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPriorityWhenSyntax<TTypeTo> IGenericBindingSyntax<T1, T2>.ToConstant<TTypeTo>(
            TTypeTo constValue)
        {
            ToConstant(constValue);
            return Copy<TTypeTo>();
        }

#if !NOEXPRESSION
        /// <summary>
        /// Adds a constructor argument for the specified argument expression.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1, T2>.To<TTypeTo>(
            Expression<Func<ResolveContext, TTypeTo>> expression, params IInjectionParameter[] bindParams)
        {
            SetToExpression(expression, bindParams);
            return Copy<TTypeTo>();
        }
#endif

        #endregion

        #region Implementation of IGenericBindingSyntax<T1,T2,T3>

        /// <summary>
        /// Indicates that the service should be bound to the specified types.
        /// </summary>
        /// <typeparam name="TTypeTo">The specified <see cref="System.Type"/>.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1, T2, T3>.To
            <TTypeTo>()
        {
            To(typeof(TTypeTo));
            return Copy<TTypeTo>();
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified method.
        /// </summary>
        /// <typeparam name="TTypeTo"></typeparam>
        /// <param name="methodBindingDelegate">The specified <see cref="MethodBindingDelegate{TTypeTo}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1, T2, T3>.ToMethod<TTypeTo>
            (
            MethodBindingDelegate<TTypeTo> methodBindingDelegate)
        {
            ToMethod(context => methodBindingDelegate(context));
            return Copy<TTypeTo>();
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constant value.
        /// </summary>
        /// <param name="constValue">The specified constant value.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPriorityWhenSyntax<TTypeTo> IGenericBindingSyntax<T1, T2, T3>.ToConstant<TTypeTo>(
            TTypeTo constValue)
        {
            ToConstant(constValue);
            return Copy<TTypeTo>();
        }

#if !NOEXPRESSION
        /// <summary>
        /// Adds a constructor argument for the specified argument expression.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1, T2, T3>.To
            <TTypeTo>(Expression<Func<ResolveContext, TTypeTo>> expression, params IInjectionParameter[] bindParams)
        {
            SetToExpression(expression, bindParams);
            return Copy<TTypeTo>();
        }
#endif

        #endregion

        #region Implementation of IGenericBindingSyntax<T1,T2,T3,T4>

        /// <summary>
        /// Indicates that the service should be bound to the specified types.
        /// </summary>
        /// <typeparam name="TTypeTo">The specified <see cref="System.Type"/>.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1, T2, T3, T4>.To
            <TTypeTo>()
        {
            To(typeof(TTypeTo));
            return Copy<TTypeTo>();
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified method.
        /// </summary>
        /// <typeparam name="TTypeTo"></typeparam>
        /// <param name="methodBindingDelegate">The specified <see cref="MethodBindingDelegate{TTypeTo}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1, T2, T3, T4>.ToMethod
            <TTypeTo>(
            MethodBindingDelegate<TTypeTo> methodBindingDelegate)
        {
            ToMethod(context => methodBindingDelegate(context));
            return Copy<TTypeTo>();
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constant value.
        /// </summary>
        /// <param name="constValue">The specified constant value.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPriorityWhenSyntax<TTypeTo> IGenericBindingSyntax<T1, T2, T3, T4>.ToConstant<TTypeTo>(
            TTypeTo constValue)
        {
            ToConstant(constValue);
            return Copy<TTypeTo>();
        }

#if !NOEXPRESSION
        /// <summary>
        /// Adds a constructor argument for the specified argument expression.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWhenWithSyntax<TTypeTo> IGenericBindingSyntax<T1, T2, T3, T4>.To
            <TTypeTo>(Expression<Func<ResolveContext, TTypeTo>> expression, params IInjectionParameter[] bindParams)
        {
            SetToExpression(expression, bindParams);
            return Copy<TTypeTo>();
        }
#endif

        #endregion

        #region Implementation of IConstantObjectSyntax

        /// <summary>
        /// Try to dispose the object after binding disposed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectSyntax TryDisposeObjects()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetTryDisposeObject();
                return this;
            }
        }

        /// <summary>
        /// Indicates that the binding should be registered with the specified name. Names are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same name.
        /// </summary>
        /// <param name="name">The name to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectSyntax NamedBinding(string name)
        {
            KeyedBinding(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be registered with the specified key. Keys are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same key.
        /// </summary>
        /// <param name="key">The key to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectSyntax KeyedBinding(object key)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetKeyedBinding(key);
                return this;
            }
        }

        /// <summary>
        /// The specified setting for build binding.
        /// </summary>
        /// <param name="key">Setting name.</param>
        /// <param name="value">Setting value.</param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectSyntax WithSetting(string key, object value)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.AddBindingSetting(key, value);
                return this;
            }
        }

        #endregion

        #region Implementation of IConstantObjectSyntax<T1>

        /// <summary>
        /// Indicates that the binding should be registered with the specified name. Names are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same name.
        /// </summary>
        /// <param name="name">The name to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantObjectSyntax<T1> IConstantObjectSyntax<T1>.NamedBinding(string name)
        {
            NamedBinding(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be registered with the specified key. Keys are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same key.
        /// </summary>
        /// <param name="key">The key to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantObjectSyntax<T1> IConstantObjectSyntax<T1>.KeyedBinding(object key)
        {
            KeyedBinding(key);
            return this;
        }

        /// <summary>
        /// The specified setting for build binding.
        /// </summary>
        /// <param name="key">Setting name.</param>
        /// <param name="value">Setting value.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantObjectSyntax<T1> IConstantObjectSyntax<T1>.WithSetting(string key, object value)
        {
            WithSetting(key, value);
            return this;
        }

        /// <summary>
        /// Try to dispose the object after binding disposed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IConstantObjectSyntax<T1> IConstantObjectSyntax<T1>.TryDisposeObjects()
        {
            TryDisposeObjects();
            return this;
        }

        #endregion

        #region Implementation of IConstantPrioritySyntax

        /// <summary>
        /// Manual set priority for binding.
        /// </summary>
        /// <param name="priority">The specified <see cref="BindingPriority"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectSyntax SetPriority(BindingPriority priority)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetPriorityBase(priority);
                return this;
            }
        }


        /// <summary>
        /// Set standard priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectSyntax SetStandardPriority()
        {
            SetPriority(BindingPriority.Standard);
            return this;
        }

        /// <summary>
        /// Set low priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectSyntax SetLowPriority()
        {
            SetPriority(BindingPriority.Low);
            return this;
        }

        /// <summary>
        /// Set normal priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectSyntax SetNormalPriority()
        {
            SetPriority(BindingPriority.Normal);
            return this;
        }

        /// <summary>
        /// Set high priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectSyntax SetHighPriority()
        {
            SetPriority(BindingPriority.High);
            return this;
        }

        #endregion

        #region Implementation of IConstantPrioritySyntax<T1>

        /// <summary>
        /// Set standard priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IConstantObjectSyntax<T1> IConstantPrioritySyntax<T1>.SetStandardPriority()
        {
            SetStandardPriority();
            return this;
        }

        /// <summary>
        /// Set low priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IConstantObjectSyntax<T1> IConstantPrioritySyntax<T1>.SetLowPriority()
        {
            SetLowPriority();
            return this;
        }

        /// <summary>
        /// Set normal priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IConstantObjectSyntax<T1> IConstantPrioritySyntax<T1>.SetNormalPriority()
        {
            SetNormalPriority();
            return this;
        }

        /// <summary>
        /// Set high priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IConstantObjectSyntax<T1> IConstantPrioritySyntax<T1>.SetHighPriority()
        {
            SetHighPriority();
            return this;
        }

        /// <summary>
        /// Manual set priority for binding.
        /// </summary>
        /// <param name="priority">The specified <see cref="BindingPriority"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantObjectSyntax<T1> IConstantPrioritySyntax<T1>.SetPriority(BindingPriority priority)
        {
            SetPriority(priority);
            return this;
        }

        #endregion

        #region Implementation of IConstantWhenSyntax

        /// <summary>
        /// Indicates that the binding should be used only for requests that support the specified condition.
        /// </summary>
        /// <param name="canResolveBindingDelegate">The specified <see cref="CanResolveBindingDelegate"/></param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectPrioritySyntax When(CanResolveBindingDelegate canResolveBindingDelegate)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetCanResolve(canResolveBindingDelegate);
                return this;
            }
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectPrioritySyntax WhenInto(Type type)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetWhenCanResolveType(type);
                return this;
            }
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectPrioritySyntax WhenInto<TType>()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetWhenCanResolveType(typeof(TType));
                return this;
            }
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectPrioritySyntax WhenIntoIsAssignable(Type type)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetWhenCanResolveTypeAssignable(type);
                return this;
            }
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectPrioritySyntax WhenIntoIsAssignable<TType>()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetWhenCanResolveTypeAssignable(typeof(TType));
                return this;
            }
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type when namespace equals.
        /// </summary>
        /// <param name="name">The name of namespace.</param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectPrioritySyntax WhenNamespaceEqual(string name)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetWhenCanResolveNamespace(name);
                return this;
            }
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <param name="attributeType">The type of attribute.</param>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectPrioritySyntax WhenClassHasAttribute(Type attributeType)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetWhenClassHasAttribute(attributeType);
                return this;
            }
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <typeparam name="T">The type of attribute.</typeparam>
        /// <returns>The fluent syntax.</returns>
        public IConstantObjectPrioritySyntax WhenClassHasAttribute<T>() where T : Attribute
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetWhenClassHasAttribute(typeof(T));
                return this;
            }
        }

        #endregion

        #region Implementation of IConstantWhenSyntax<T1>

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPrioritySyntax<T1> IConstantWhenSyntax<T1>.WhenInto(Type type)
        {
            WhenInto(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPrioritySyntax<T1> IConstantWhenSyntax<T1>.WhenInto<TType>()
        {
            WhenInto<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPrioritySyntax<T1> IConstantWhenSyntax<T1>.WhenIntoIsAssignable(Type type)
        {
            WhenIntoIsAssignable(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPrioritySyntax<T1> IConstantWhenSyntax<T1>.WhenIntoIsAssignable<TType>()
        {
            WhenIntoIsAssignable<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type when namespace equals.
        /// </summary>
        /// <param name="name">The name of namespace.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPrioritySyntax<T1> IConstantWhenSyntax<T1>.WhenNamespaceEqual(string name)
        {
            WhenNamespaceEqual(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <param name="attributeType">The type of attribute.</param>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPrioritySyntax<T1> IConstantWhenSyntax<T1>.WhenClassHasAttribute(Type attributeType)
        {
            WhenClassHasAttribute(attributeType);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <typeparam name="TAttribute">The type of attribute.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPrioritySyntax<T1> IConstantWhenSyntax<T1>.WhenClassHasAttribute<TAttribute>()
        {
            WhenClassHasAttribute<TAttribute>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for requests that support the specified condition.
        /// </summary>
        /// <param name="canResolveBindingDelegate">The specified <see cref="CanResolveBindingDelegate"/></param>
        /// <returns>The fluent syntax.</returns>
        IConstantCallbackObjectPrioritySyntax<T1> IConstantWhenSyntax<T1>.When(CanResolveBindingDelegate canResolveBindingDelegate)
        {
            When(canResolveBindingDelegate);
            return this;
        }

        #endregion

        #region Implementation of IMethodCallbackSyntax

        /// <summary>
        /// Execute callback method before binding activated.
        /// </summary>
        /// <param name="onActivating">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax OnActivating(Action<IBindingContext> onActivating)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetOnActivating(onActivating);
                return this;
            }
        }

        /// <summary>
        ///     Indicates that the binding should executes callback method after binding activated.
        /// </summary>
        /// <param name="onActivated">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax OnActivated(Action<object> onActivated)
        {
            Validate.ArgumentNotNull(onActivated, "onActivated");
            using (_configurator.BeginConfigure)
            {
                _configurator.SetOnActivated((IBinding binding, IBindingContext context, ref object instance) => onActivated(instance));
                return this;
            }
        }

        /// <summary>
        /// Execute callback method after binding activated.
        /// </summary>
        /// <param name="onActivated">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax OnActivated(BindingActivatedDelegate<object> onActivated)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetOnActivated(onActivated);
                return this;
            }
        }

        /// <summary>
        ///     Executes the callback that should be called before instances are released.
        /// </summary>
        /// <param name="onReleaseObject">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax OnReleaseObject(Action<object, bool> onReleaseObject)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetOnReleaseObject(onReleaseObject);
                return this;
            }
        }

        /// <summary>
        /// Execute callback method after binding disposed.
        /// </summary>
        /// <param name="onDisposed">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax OnDisposed(Action<IBinding> onDisposed)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetOnDisposed(onDisposed);
                return this;
            }
        }

        #endregion

        #region Implementation of IMethodCallbackSyntax<T1>

        /// <summary>
        /// Execute callback method after binding activated.
        /// </summary>
        /// <param name="onActivated">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax<T1> OnActivated(BindingActivatedDelegate<T1> onActivated)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(onActivated, "onActivated");
                _configurator.SetOnActivated((IBinding binding, IBindingContext context, ref object instance) =>
                                                 {
                                                     var obj = (T1)instance;
                                                     onActivated(binding, context, ref obj);
                                                     instance = obj;
                                                 });
                return this;
            }
        }

        /// <summary>
        ///     Indicates that the binding should executes callback method after binding activated.
        /// </summary>
        /// <param name="onActivated">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax<T1> OnActivated(Action<T1> onActivated)
        {
            Validate.ArgumentNotNull(onActivated, "onActivated");
            using (_configurator.BeginConfigure)
            {
                _configurator.SetOnActivated((IBinding binding, IBindingContext context, ref object instance) => onActivated((T1) instance));
                return this;
            }
        }

        /// <summary>
        /// Execute callback method after binding disposed.
        /// </summary>
        /// <param name="onDisposed">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodCallbackSyntax<T1>.OnDisposed(Action<IBinding> onDisposed)
        {
            OnDisposed(onDisposed);
            return this;
        }

        /// <summary>
        ///     Executes the callback that should be called before instances are released.
        /// </summary>
        /// <param name="onReleaseObject">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax<T1> OnReleaseObject(Action<T1, bool> onReleaseObject)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(onReleaseObject, "onReleaseObject");
                _configurator.SetOnReleaseObject((o, b) => onReleaseObject((T1)o, b));
                return this;
            }
        }

        /// <summary>
        /// Execute callback method before binding activated.
        /// </summary>
        /// <param name="onActivating">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodCallbackSyntax<T1>.OnActivating(Action<IBindingContext> onActivating)
        {
            OnActivating(onActivating);
            return this;
        }

        #endregion

        #region Implementation of IMethodObjectSyntax

        /// <summary>
        /// Try to dispose the object after binding disposed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax IMethodObjectSyntax.TryDisposeObjects()
        {
            TryDisposeObjects();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be registered with the specified name. Names are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same name.
        /// </summary>
        /// <param name="name">The name to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax IMethodObjectSyntax.NamedBinding(string name)
        {
            NamedBinding(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be registered with the specified key. Keys are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same key.
        /// </summary>
        /// <param name="key">The key to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax IMethodObjectSyntax.KeyedBinding(object key)
        {
            KeyedBinding(key);
            return this;
        }

        /// <summary>
        /// The specified setting for build binding.
        /// </summary>
        /// <param name="key">Setting name.</param>
        /// <param name="value">Setting value.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax IMethodObjectSyntax.WithSetting(string key, object value)
        {
            WithSetting(key, value);
            return this;
        }

        #endregion

        #region Implementation of IMethodObjectSyntax<T1>

        /// <summary>
        /// Indicates that the binding should be registered with the specified name. Names are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same name.
        /// </summary>
        /// <param name="name">The name to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodObjectSyntax<T1>.NamedBinding(string name)
        {
            NamedBinding(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be registered with the specified key. Keys are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same key.
        /// </summary>
        /// <param name="key">The key to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodObjectSyntax<T1>.KeyedBinding(object key)
        {
            KeyedBinding(key);
            return this;
        }

        /// <summary>
        /// The specified setting for build binding.
        /// </summary>
        /// <param name="key">Setting name.</param>
        /// <param name="value">Setting value.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodObjectSyntax<T1>.WithSetting(string key, object value)
        {
            WithSetting(key, value);
            return this;
        }

        /// <summary>
        /// Try to dispose the object after binding disposed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodObjectSyntax<T1>.TryDisposeObjects()
        {
            TryDisposeObjects();
            return this;
        }

        #endregion

        #region Implementation of IMethodPrioritySyntax

        /// <summary>
        /// Manual set priority for binding.
        /// </summary>
        /// <param name="priority">The specified <see cref="BindingPriority"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax IMethodPrioritySyntax.SetPriority(BindingPriority priority)
        {
            SetPriority(priority);
            return this;
        }

        /// <summary>
        /// Set standard priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax IMethodPrioritySyntax.SetStandardPriority()
        {
            SetStandardPriority();
            return this;
        }

        /// <summary>
        /// Set low priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax IMethodPrioritySyntax.SetLowPriority()
        {
            SetLowPriority();
            return this;
        }

        /// <summary>
        /// Set normal priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax IMethodPrioritySyntax.SetNormalPriority()
        {
            SetNormalPriority();
            return this;
        }

        /// <summary>
        /// Set hight priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax IMethodPrioritySyntax.SetHighPriority()
        {
            SetHighPriority();
            return this;
        }

        #endregion

        #region Implementation of IMethodPrioritySyntax<T1>

        /// <summary>
        /// Set standard priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodPrioritySyntax<T1>.SetStandardPriority()
        {
            SetStandardPriority();
            return this;
        }

        /// <summary>
        /// Set low priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodPrioritySyntax<T1>.SetLowPriority()
        {
            SetLowPriority();
            return this;
        }

        /// <summary>
        /// Set normal priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodPrioritySyntax<T1>.SetNormalPriority()
        {
            SetNormalPriority();
            return this;
        }

        /// <summary>
        /// Set hight priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodPrioritySyntax<T1>.SetHighPriority()
        {
            SetHighPriority();
            return this;
        }

        /// <summary>
        /// Manual set priority for binding.
        /// </summary>
        /// <param name="priority">The specified <see cref="BindingPriority"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodPrioritySyntax<T1>.SetPriority(BindingPriority priority)
        {
            SetPriority(priority);
            return this;
        }

        #endregion

        #region Implementation of IMethodScopeSyntax

        /// <summary>
        ///  Indicates that instances activated via the custom lifecycle managment.
        /// </summary>
        /// <param name="customScopeDelegate">The specified <see cref="CustomScopeDelegate"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityUseWithSyntax InScope(CustomScopeDelegate customScopeDelegate)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetScope(customScopeDelegate);
                return this;
            }
        }

        /// <summary>
        ///  Indicates that instances activated via the specified lifecycle
        /// </summary>
        /// <param name="scopeLifecycle">The specified <see cref="IScopeLifecycle"/>. </param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityUseWithSyntax InScope(IScopeLifecycle scopeLifecycle)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(scopeLifecycle, "scopeLifecycle");
                _configurator.SetScope(() => scopeLifecycle);
                return this;
            }
        }

        /// <summary>
        /// Indicates that only a single instance of the binding should be created, and then
        /// should be re-used for all subsequent requests.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityUseWithSyntax InSingletonScope()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetScope(() => new SingletonScopeLifecycle());
                return this;
            }
        }

        /// <summary>
        /// Indicates that instances activated via the binding should be re-used within the same thread.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityUseWithSyntax InThreadScope()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetScope(() => new ThreadScopeLifecycle());
                return this;
            }
        }

        /// <summary>
        /// Indicates that instances activated via the binding should not be re-used, nor have their lifecycle managed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityUseWithSyntax InTransientScope()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetScope(() => new TransientScopeLifecycle());
                return this;
            }
        }

        /// <summary>
        ///Indicates that only a single instance of the binding should be created in each <see cref="IInjector"/>, and then
        /// should be re-used for all subsequent requests. 
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityUseWithSyntax InUnitOfWorkScope()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetScope(() => new UnitOfWorkScopeLifecycle());
                return this;
            }
        }

        /// <summary>
        ///  Indicates that instances activated via the <see cref="IManagedScope"/> lifecycle managment.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityUseWithSyntax InManagedScope()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetScope(() => new ManagedScopeLifecycle());
                return this;
            }
        }

        /// <summary>
        /// Indicates that instances activated via the binding should be re-used as weak reference.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectPriorityUseWithSyntax InWeakReferenceScope()
        {
            InScope(new WeakReferenceScopeLifecycle());
            return this;
        }

        #endregion

        #region Implementation of IMethodScopeSyntax<T1>

        /// <summary>
        ///  Indicates that instances activated via the specified lifecycle
        /// </summary>
        /// <param name="scopeLifecycle">The specified <see cref="IScopeLifecycle"/>. </param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityUseWithSyntax<T1> IMethodScopeSyntax<T1>.InScope(IScopeLifecycle scopeLifecycle)
        {
            InScope(scopeLifecycle);
            return this;
        }

        /// <summary>
        /// Indicates that only a single instance of the binding should be created, and then
        /// should be re-used for all subsequent requests.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityUseWithSyntax<T1> IMethodScopeSyntax<T1>.InSingletonScope()
        {
            InSingletonScope();
            return this;
        }

        /// <summary>
        /// Indicates that instances activated via the binding should be re-used within the same thread.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityUseWithSyntax<T1> IMethodScopeSyntax<T1>.InThreadScope()
        {

            InThreadScope();
            return this;
        }

        /// <summary>
        /// Indicates that instances activated via the binding should not be re-used, nor have their lifecycle managed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityUseWithSyntax<T1> IMethodScopeSyntax<T1>.InTransientScope()
        {
            InTransientScope();
            return this;
        }

        /// <summary>
        ///Indicates that only a single instance of the binding should be created in each <see cref="IInjector"/>, and then
        /// should be re-used for all subsequent requests. 
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityUseWithSyntax<T1> IMethodScopeSyntax<T1>.InUnitOfWorkScope()
        {
            InUnitOfWorkScope();
            return this;
        }

        /// <summary>
        ///  Indicates that instances activated via the <see cref="IManagedScope"/> lifecycle managment.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityUseWithSyntax<T1> IMethodScopeSyntax<T1>.InManagedScope()
        {
            InManagedScope();
            return this;
        }

        /// <summary>
        ///  Indicates that instances activated via the custom lifecycle managment.
        /// </summary>
        /// <param name="customScopeDelegate">The specified <see cref="CustomScopeDelegate"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityUseWithSyntax<T1> IMethodScopeSyntax<T1>.InScope(CustomScopeDelegate customScopeDelegate)
        {

            InScope(customScopeDelegate);
            return this;
        }

        /// <summary>
        /// Indicates that instances activated via the binding should be re-used as weak reference.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityUseWithSyntax<T1> IMethodScopeSyntax<T1>.InWeakReferenceScope()
        {
            InWeakReferenceScope();
            return this;
        }

        #endregion

        #region Implementation of IMethodWhenSyntax

        /// <summary>
        /// Indicates that the binding should be used only for requests that support the specified condition.
        /// </summary>
        /// <param name="canResolveBindingDelegate">The specified <see cref="CanResolveBindingDelegate"/></param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax IMethodWhenSyntax.When(
            CanResolveBindingDelegate canResolveBindingDelegate)
        {
            When(canResolveBindingDelegate);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax IMethodWhenSyntax.WhenInto(Type type)
        {
            WhenInto(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax IMethodWhenSyntax.WhenInto<TType>()
        {
            WhenInto<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax IMethodWhenSyntax.WhenIntoIsAssignable(Type type)
        {
            WhenIntoIsAssignable(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax IMethodWhenSyntax.WhenIntoIsAssignable<TType>()
        {
            WhenIntoIsAssignable<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type when namespace equals.
        /// </summary>
        /// <param name="name">The name of namespace.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax IMethodWhenSyntax.WhenNamespaceEqual(string name)
        {
            WhenNamespaceEqual(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <param name="attributeType">The type of attribute.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax IMethodWhenSyntax.WhenClassHasAttribute(Type attributeType)
        {
            WhenClassHasAttribute(attributeType);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <typeparam name="T">The type of attribute.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax IMethodWhenSyntax.WhenClassHasAttribute<T>()
        {
            WhenClassHasAttribute<T>();
            return this;
        }

        #endregion

        #region Implementation of IMethodWhenSyntax<T1>

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T1> IMethodWhenSyntax<T1>.WhenInto(Type type)
        {
            WhenInto(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T1> IMethodWhenSyntax<T1>.WhenInto<TType>()
        {
            WhenInto<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T1> IMethodWhenSyntax<T1>.WhenIntoIsAssignable(Type type)
        {
            WhenIntoIsAssignable(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T1> IMethodWhenSyntax<T1>.WhenIntoIsAssignable<TType>()
        {
            WhenInto<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type when namespace equals.
        /// </summary>
        /// <param name="name">The name of namespace.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T1> IMethodWhenSyntax<T1>.WhenNamespaceEqual(string name)
        {
            WhenNamespaceEqual(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <param name="attributeType">The type of attribute.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T1> IMethodWhenSyntax<T1>.WhenClassHasAttribute(Type attributeType)
        {
            WhenClassHasAttribute(attributeType);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <typeparam name="TAttribute">The type of attribute.</typeparam>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T1> IMethodWhenSyntax<T1>.WhenClassHasAttribute<TAttribute>()
        {
            WhenClassHasAttribute<TAttribute>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for requests that support the specified condition.
        /// </summary>
        /// <param name="canResolveBindingDelegate">The specified <see cref="CanResolveBindingDelegate"/></param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectPriorityScopeUseWithSyntax<T1> IMethodWhenSyntax<T1>.When(CanResolveBindingDelegate canResolveBindingDelegate)
        {
            When(canResolveBindingDelegate);
            return this;
        }

        #endregion

        #region Implementation of IMethodWithSyntax

        /// <summary>
        /// Use specified constructor argument.
        /// </summary>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="value">The specified parameter value.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax WithConstructorArgument(string name, object value)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.AddParameter(new ConstructorParameter(name, value));
                return this;
            }
        }

        /// <summary>
        /// Use specified constructor argument.
        /// </summary>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax WithConstructorArgument(string name, ParameterDelegate<object> parameterDelegate)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.AddParameter(new ConstructorParameter(name, parameterDelegate));
                return this;
            }
        }

        /// <summary>
        /// Use specified method argument.
        /// </summary>
        /// <param name="methodName">The specified method name.</param>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="value">The specified parameter value.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax WithMethodArgument(string methodName, string name, object value)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.AddParameter(new MethodParameter(methodName, name, value));
                return this;
            }
        }

        /// <summary>
        /// Use specified method argument.
        /// </summary>
        /// <param name="methodName"></param>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax WithMethodArgument(string methodName, string name, ParameterDelegate<object> parameterDelegate)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.AddParameter(new MethodParameter(methodName, name, parameterDelegate));
                return this;
            }
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="name">The specified property name.</param>
        /// <param name="value">The specified property value.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax WithPropertyValue(string name, object value)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.AddParameter(new PropertyParameter(name, value));
                return this;
            }
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="name">The specified property name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax WithPropertyValue(string name, ParameterDelegate<object> parameterDelegate)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.AddParameter(new PropertyParameter(name, parameterDelegate));
                return this;
            }
        }

        /// <summary>
        /// Use specified custom argument.
        /// </summary>
        /// <param name="parameter">The specified <see cref="IInjectionParameter"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax WithParameter(IInjectionParameter parameter)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(parameter, "parameter");
                _configurator.AddParameter(parameter);
                return this;
            }
        }

        #endregion

        #region Implementation of IMethodUseSyntax

        /// <summary>
        /// Use reflection activator for activate instance.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax UseReflectionActivator()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetActivator(() => new ReflectionActivator());
                return this;
            }
        }

#if !NETFX_CORE
        /// <summary>
        /// Use emit activator for activate instance.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax UseEmitActivator()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetActivator(() => new EmitActivator());
                return this;
            }
        }
#endif


#if !NOEXPRESSION
        /// <summary>
        /// Use expression activator for activate instance.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax UseExpressionActivator()
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetActivator(() => new ExpressionActivator());
                return this;
            }
        }
#endif


        /// <summary>
        /// Use custom activator for activate instance.
        /// </summary>
        /// <param name="activator">The specified <see cref="IActivator"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax UseCustomActivator(IActivator activator)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(activator, "activator");
                _configurator.SetActivator(() => activator);
                return this;
            }
        }

        /// <summary>
        /// Use custom activator for activate instance.
        /// </summary>
        /// <param name="methodActivator">The specified <see cref="Func{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax UseCustomActivator(Func<IActivator> methodActivator)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.SetActivator(methodActivator);
                return this;
            }
        }

        #endregion

        #region Implementation of IMethodUseSyntax<T1>

#if !NETFX_CORE
        /// <summary>
        /// Use emit activator for activate instance.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodUseSyntax<T1>.UseEmitActivator()
        {
            UseEmitActivator();
            return this;
        }
#endif


#if !NOEXPRESSION
        /// <summary>
        /// Use expression activator for activate instance.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodUseSyntax<T1>.UseExpressionActivator()
        {
            UseExpressionActivator();
            return this;
        }
#endif
        /// <summary>
        /// Use custom activator for activate instance.
        /// </summary>
        /// <param name="activator">The specified <see cref="IActivator"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodUseSyntax<T1>.UseCustomActivator(IActivator activator)
        {
            UseCustomActivator(activator);
            return this;
        }

        /// <summary>
        /// Use custom activator for activate instance.
        /// </summary>
        /// <param name="methodActivator">The specified <see cref="Func{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodUseSyntax<T1>.UseCustomActivator(Func<IActivator> methodActivator)
        {
            UseCustomActivator(methodActivator);
            return this;
        }

        /// <summary>
        /// Use reflection activator for activate instance.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodUseSyntax<T1>.UseReflectionActivator()
        {
            UseReflectionActivator();
            return this;
        }

        #endregion

        #region Implementation of ITypeCallbackSyntax

        /// <summary>
        /// Execute callback method before binding activated.
        /// </summary>
        /// <param name="onActivating">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeCallbackSyntax.OnActivating(Action<IBindingContext> onActivating)
        {
            OnActivating(onActivating);
            return this;
        }

        /// <summary>
        ///     Indicates that the binding should executes callback method after binding activated.
        /// </summary>
        /// <param name="onActivated">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeCallbackSyntax.OnActivated(Action<object> onActivated)
        {
            OnActivated(onActivated);
            return this;
        }

        /// <summary>
        /// Execute callback method after binding activated.
        /// </summary>
        /// <param name="onActivated">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeCallbackSyntax.OnActivated(BindingActivatedDelegate<object> onActivated)
        {
            OnActivated(onActivated);
            return this;
        }

        /// <summary>
        ///     Executes the callback that should be called before instances are released.
        /// </summary>
        /// <param name="onReleaseObject">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeCallbackSyntax.OnReleaseObject(Action<object, bool> onReleaseObject)
        {
            OnReleaseObject(onReleaseObject);
            return this;
        }

        /// <summary>
        /// Execute callback method after binding disposed.
        /// </summary>
        /// <param name="onDisposed">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeCallbackSyntax.OnDisposed(Action<IBinding> onDisposed)
        {
            OnDisposed(onDisposed);
            return this;
        }

        #endregion

        #region Implementation of ITypeCallbackSyntax<T1>

        /// <summary>
        ///     Indicates that the binding should executes callback method after binding activated.
        /// </summary>
        /// <param name="onActivated">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeCallbackSyntax<T1>.OnActivated(Action<T1> onActivated)
        {
            OnActivated(onActivated);
            return this;
        }

        /// <summary>
        /// Execute callback method after binding activated.
        /// </summary>
        /// <param name="onActivated">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeCallbackSyntax<T1>.OnActivated(BindingActivatedDelegate<T1> onActivated)
        {
            OnActivated(onActivated);
            return this;
        }

        /// <summary>
        /// Execute callback method after binding disposed.
        /// </summary>
        /// <param name="onDisposed">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeCallbackSyntax<T1>.OnDisposed(Action<IBinding> onDisposed)
        {
            OnDisposed(onDisposed);
            return this;
        }

        /// <summary>
        ///     Executes the callback that should be called before instances are released.
        /// </summary>
        /// <param name="onReleaseObject">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeCallbackSyntax<T1>.OnReleaseObject(Action<T1, bool> onReleaseObject)
        {
            OnReleaseObject(onReleaseObject);
            return this;
        }

        /// <summary>
        /// Execute callback method before binding activated.
        /// </summary>
        /// <param name="onActivating">The specified callback method.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeCallbackSyntax<T1>.OnActivating(Action<IBindingContext> onActivating)
        {
            OnActivating(onActivating);
            return this;
        }

        #endregion

        #region Implementation of ITypeConstructorSyntax

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <param name="types">The specified parameters for search constructor.</param>
        /// <returns>The fluent syntax.</returns>
        public ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor(params Type[] types)
        {
            using (_configurator.BeginConfigure)
            {
                _configurator.CheckConstructor();
#if NETFX_CORE
            var constructorInfo = _configurator.TypeToValue.GetConstructor(types);
#else
                ConstructorInfo constructorInfo = _configurator.TypeToValue.GetConstructor(
                    BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.CreateInstance,
                    null, types, null);
#endif

                if (constructorInfo == null)
                    throw new InvalidBindingException(
                        string.Format("The constructor with {0} type(s) not found in service {1}.",
                                      InjectorUtilsInternal.FormatTypes(types), InjectorUtilsInternal.FormatType(_configurator.TypeToValue)));
                _configurator.Constructor = constructorInfo;
                return this;
            }
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T11>()
        {
            return TakeConstructor(new[] { typeof(T11) });
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T11, T21>()
        {
            return TakeConstructor(new[] { typeof(T11), typeof(T21) });
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T11, T21, T31>()
        {
            return TakeConstructor(new[] { typeof(T11), typeof(T21), typeof(T31) });
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T11, T21, T31, T41>()
        {
            return TakeConstructor(new[] { typeof(T11), typeof(T21), typeof(T31), typeof(T41) });
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        public ITypeCallbackObjectPriorityUseWithSyntax TakeConstructor<T11, T21, T31, T41, T5>()
        {
            return TakeConstructor(new[] { typeof(T11), typeof(T21), typeof(T31), typeof(T41), typeof(T5) });
        }

        #endregion

        #region Implementation of ITypeConstructorSyntax<T1>

#if NOEXPRESSION
        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T1> ITypeConstructorSyntax<T1>.TakeConstructor<T11>()
        {
            TakeConstructor<T11>();
            return this;
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T1> ITypeConstructorSyntax<T1>.TakeConstructor<T11, T21>()
        {
            TakeConstructor<T11, T21>();
            return this;
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T1> ITypeConstructorSyntax<T1>.TakeConstructor<T11, T21, T31>()
        {
            TakeConstructor<T11, T21, T31>();
            return this;
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T1> ITypeConstructorSyntax<T1>.TakeConstructor<T11, T21, T31, T41>()
        {
            TakeConstructor<T11, T21, T31, T41>();
            return this;
        }

        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T1> ITypeConstructorSyntax<T1>.TakeConstructor<T11, T21, T31, T41, T5>()
        {
            TakeConstructor<T11, T21, T31, T41, T5>();
            return this;
        }
#else
        /// <summary>
        /// Use specified property argument.
        /// </summary>
        /// <param name="constructor">The constructor expression.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T1> ITypeConstructorSyntax<T1>.TakeConstructor(Expression<Func<ResolveContext, T1>> constructor)
        {
            Validate.ArgumentNotNull(constructor, "constructor");
            var newExpression = InjectorUtilsInternal.ParseNewExpression(constructor);
            _configurator.Constructor = newExpression.Constructor;
            return this;
        }

#endif
        /// <summary>
        /// Indicates that the service should be bound to the specified constructor.
        /// </summary>
        /// <param name="types">The specified parameters for search constructor.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectPriorityUseWithSyntax<T1> ITypeConstructorSyntax<T1>.TakeConstructor(params Type[] types)
        {
            TakeConstructor(types);
            return this;
        }


        #endregion

        #region Implementation of ITypeObjectSyntax

        /// <summary>
        /// Try to dispose the object after binding disposed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeObjectSyntax.TryDisposeObjects()
        {
            TryDisposeObjects();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be registered with the specified name. Names are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same name.
        /// </summary>
        /// <param name="name">The name to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeObjectSyntax.NamedBinding(string name)
        {
            NamedBinding(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be registered with the specified key. Keys are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same key.
        /// </summary>
        /// <param name="key">The key to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeObjectSyntax.KeyedBinding(object key)
        {
            KeyedBinding(key);
            return this;
        }

        /// <summary>
        /// The specified setting for build binding.
        /// </summary>
        /// <param name="key">Setting name.</param>
        /// <param name="value">Setting value.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeObjectSyntax.WithSetting(string key, object value)
        {
            WithSetting(key, value);
            return this;
        }

        #endregion

        #region Implementation of ITypeObjectSyntax<T1>

        /// <summary>
        /// Indicates that the binding should be registered with the specified name. Names are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same name.
        /// </summary>
        /// <param name="name">The name to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeObjectSyntax<T1>.NamedBinding(string name)
        {
            NamedBinding(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be registered with the specified key. Keys are not
        /// necessarily unique; multiple bindings for a given service may be registered with the same key.
        /// </summary>
        /// <param name="key">The key to give the binding.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeObjectSyntax<T1>.KeyedBinding(object key)
        {
            KeyedBinding(key);
            return this;
        }

        /// <summary>
        /// The specified setting for build binding.
        /// </summary>
        /// <param name="key">Setting name.</param>
        /// <param name="value">Setting value.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeObjectSyntax<T1>.WithSetting(string key, object value)
        {
            WithSetting(key, value);
            return this;
        }

        /// <summary>
        /// Try to dispose the object after binding disposed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeObjectSyntax<T1>.TryDisposeObjects()
        {
            TryDisposeObjects();
            return this;
        }

        #endregion

        #region Implementation of ITypePrioritySyntax

        /// <summary>
        /// Manual set priority for binding.
        /// </summary>
        /// <param name="priority">The specified <see cref="BindingPriority"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypePrioritySyntax.SetPriority(BindingPriority priority)
        {
            SetPriority(priority);
            return this;
        }

        /// <summary>
        /// Set standard priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypePrioritySyntax.SetStandardPriority()
        {
            SetStandardPriority();
            return this;
        }

        /// <summary>
        /// Set low priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypePrioritySyntax.SetLowPriority()
        {
            SetLowPriority();
            return this;
        }

        /// <summary>
        /// Set normal priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypePrioritySyntax.SetNormalPriority()
        {
            SetNormalPriority();
            return this;
        }

        /// <summary>
        /// Set high priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypePrioritySyntax.SetHighPriority()
        {
            SetHighPriority();
            return this;
        }

        #endregion

        #region Implementation of ITypePrioritySyntax<T1>

        /// <summary>
        /// Set standard priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypePrioritySyntax<T1>.SetStandardPriority()
        {
            SetStandardPriority();
            return this;
        }

        /// <summary>
        /// Set low priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypePrioritySyntax<T1>.SetLowPriority()
        {
            SetLowPriority();
            return this;
        }

        /// <summary>
        /// Set normal priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypePrioritySyntax<T1>.SetNormalPriority()
        {
            SetNormalPriority();
            return this;
        }

        /// <summary>
        /// Set high priority for binding.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypePrioritySyntax<T1>.SetHighPriority()
        {
            SetHighPriority();
            return this;
        }

        /// <summary>
        /// Manual set priority for binding.
        /// </summary>
        /// <param name="priority">The specified <see cref="BindingPriority"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypePrioritySyntax<T1>.SetPriority(BindingPriority priority)
        {
            SetPriority(priority);
            return this;
        }

        #endregion

        #region Implementation of ITypeScopeSyntax

        /// <summary>
        ///  Indicates that instances activated via the custom lifecycle managment.
        /// </summary>
        /// <param name="customScopeDelegate">The specified <see cref="CustomScopeDelegate"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax ITypeScopeSyntax.InScope(
            CustomScopeDelegate customScopeDelegate)
        {
            InScope(customScopeDelegate);
            return this;
        }

        /// <summary>
        ///  Indicates that instances activated via the specified lifecycle
        /// </summary>
        /// <param name="scopeLifecycle">The specified <see cref="IScopeLifecycle"/>. </param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax ITypeScopeSyntax.InScope(IScopeLifecycle scopeLifecycle)
        {
            InScope(scopeLifecycle);
            return this;
        }

        /// <summary>
        /// Indicates that only a single instance of the binding should be created, and then
        /// should be re-used for all subsequent requests.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax ITypeScopeSyntax.InSingletonScope()
        {
            InSingletonScope();
            return this;
        }

        /// <summary>
        /// Indicates that instances activated via the binding should be re-used within the same thread.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax ITypeScopeSyntax.InThreadScope()
        {
            InThreadScope();
            return this;
        }

        /// <summary>
        /// Indicates that instances activated via the binding should not be re-used, nor have their lifecycle managed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax ITypeScopeSyntax.InTransientScope()
        {
            InTransientScope();
            return this;
        }

        /// <summary>
        /// Indicates that only a single instance of the binding should be created in each <see cref="IInjector"/>, and then
        /// should be re-used for all subsequent requests. 
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax ITypeScopeSyntax.InUnitOfWorkScope()
        {
            InUnitOfWorkScope();
            return this;
        }

        /// <summary>
        ///  Indicates that instances activated via the <see cref="IManagedScope"/> lifecycle managment.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax ITypeScopeSyntax.InManagedScope()
        {
            InManagedScope();
            return this;
        }

        /// <summary>
        /// Indicates that instances activated via the binding should be re-used as weak reference.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax ITypeScopeSyntax.InWeakReferenceScope()
        {
            InWeakReferenceScope();
            return this;
        }

        #endregion

        #region Implementation of ITypeScopeSyntax<T1>

        /// <summary>
        ///  Indicates that instances activated via the specified lifecycle
        /// </summary>
        /// <param name="scopeLifecycle">The specified <see cref="IScopeLifecycle"/>. </param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax<T1> ITypeScopeSyntax<T1>.InScope(
            IScopeLifecycle scopeLifecycle)
        {
            InScope(scopeLifecycle);
            return this;
        }

        /// <summary>
        /// Indicates that only a single instance of the binding should be created, and then
        /// should be re-used for all subsequent requests.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax<T1> ITypeScopeSyntax<T1>.InSingletonScope()
        {
            InSingletonScope();
            return this;
        }

        /// <summary>
        /// Indicates that instances activated via the binding should be re-used within the same thread.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax<T1> ITypeScopeSyntax<T1>.InThreadScope()
        {
            InThreadScope();
            return this;
        }

        /// <summary>
        /// Indicates that instances activated via the binding should not be re-used, nor have their lifecycle managed.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax<T1> ITypeScopeSyntax<T1>.InTransientScope()
        {
            InTransientScope();
            return this;
        }

        /// <summary>
        /// Indicates that only a single instance of the binding should be created in each <see cref="IInjector"/>, and then
        /// should be re-used for all subsequent requests. 
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax<T1> ITypeScopeSyntax<T1>.InUnitOfWorkScope()
        {
            InUnitOfWorkScope();
            return this;
        }

        /// <summary>
        ///  Indicates that instances activated via the <see cref="IManagedScope"/> lifecycle managment.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax<T1> ITypeScopeSyntax<T1>.InManagedScope()
        {
            InManagedScope();
            return this;
        }

        /// <summary>
        ///  Indicates that instances activated via the custom lifecycle managment.
        /// </summary>
        /// <param name="customScopeDelegate">The specified <see cref="CustomScopeDelegate"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax<T1> ITypeScopeSyntax<T1>.InScope(CustomScopeDelegate customScopeDelegate)
        {
            InScope(customScopeDelegate);
            return this;
        }

        /// <summary>
        /// Indicates that instances activated via the binding should be re-used as weak reference.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityUseWithSyntax<T1> ITypeScopeSyntax<T1>.InWeakReferenceScope()
        {
            InWeakReferenceScope();
            return this;
        }

        #endregion

        #region Implementation of ITypeUseSyntax

        /// <summary>
        /// Use reflection activator for create new instance of object.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeUseSyntax.UseReflectionActivator()
        {
            UseReflectionActivator();
            return this;
        }

#if !NETFX_CORE
        /// <summary>
        /// Use emit activator for create new instance of object.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeUseSyntax.UseEmitActivator()
        {
            UseEmitActivator();
            return this;
        }
#endif


#if !NOEXPRESSION
        /// <summary>
        /// Use expression activator for create new instance of object.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeUseSyntax.UseExpressionActivator()
        {
            UseExpressionActivator();
            return this;
        }
#endif

        /// <summary>
        /// Use custom activator for create new instance of object.
        /// </summary>
        /// <param name="activator">The specified <see cref="IActivator"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeUseSyntax.UseCustomActivator(IActivator activator)
        {
            UseCustomActivator(activator);
            return this;
        }

        /// <summary>
        /// Use custom activator for create new instance of object.
        /// </summary>
        /// <param name="methodActivator">The specified <see cref="Func{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeUseSyntax.UseCustomActivator(Func<IActivator> methodActivator)
        {
            UseCustomActivator(methodActivator);
            return this;
        }

        /// <summary>
        /// Use custom constructor resolver for select constructor for specified service.
        /// </summary>
        /// <param name="constructorResolver">The specified <see cref="IConstructorResolver"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public ITypeCallbackObjectUseWithSyntax UseCustomConstructorResolver(IConstructorResolver constructorResolver)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(constructorResolver, "constructorResolver");
                _configurator.CheckConstructorResolver();
                _configurator.ConstructorResolverFunc = () => constructorResolver;
                return this;
            }
        }

        /// <summary>
        /// Use custom constructor resolver for select constructor for specified service.
        /// </summary>
        /// <param name="constructorResolver">The specified <see cref="Func{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        public ITypeCallbackObjectUseWithSyntax UseCustomConstructorResolver(Func<IConstructorResolver> constructorResolver)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(constructorResolver, "constructorResolver");
                _configurator.CheckConstructorResolver();
                _configurator.ConstructorResolverFunc = constructorResolver;
                return this;
            }
        }

        #endregion

        #region Implementation of ITypeUseSyntax<T1>

#if !NETFX_CORE
        /// <summary>
        /// Use emit activator for create new instance of object.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeUseSyntax<T1>.UseEmitActivator()
        {
            UseEmitActivator();
            return this;
        }
#endif
#if !NOEXPRESSION
        /// <summary>
        /// Use expression activator for create new instance of object.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeUseSyntax<T1>.UseExpressionActivator()
        {
            UseExpressionActivator();
            return this;
        }
#endif
        /// <summary>
        /// Use custom activator for create new instance of object.
        /// </summary>
        /// <param name="activator">The specified <see cref="IActivator"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeUseSyntax<T1>.UseCustomActivator(IActivator activator)
        {
            UseCustomActivator(activator);
            return this;
        }

        /// <summary>
        /// Use custom activator for create new instance of object.
        /// </summary>
        /// <param name="methodActivator">The specified <see cref="Func{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeUseSyntax<T1>.UseCustomActivator(Func<IActivator> methodActivator)
        {
            UseCustomActivator(methodActivator);
            return this;
        }

        /// <summary>
        /// Use custom constructor resolver for select constructor for specified service.
        /// </summary>
        /// <param name="constructorResolver">The specified <see cref="IConstructorResolver"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeUseSyntax<T1>.UseCustomConstructorResolver(
            IConstructorResolver constructorResolver)
        {
            UseCustomConstructorResolver(constructorResolver);
            return this;
        }

        /// <summary>
        /// Use custom constructor resolver for select constructor for specified service.
        /// </summary>
        /// <param name="constructorResolver">The specified <see cref="Func{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeUseSyntax<T1>.UseCustomConstructorResolver(
            Func<IConstructorResolver> constructorResolver)
        {
            UseCustomConstructorResolver(constructorResolver);
            return this;
        }

        /// <summary>
        /// Use reflection activator for create new instance of object.
        /// </summary>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeUseSyntax<T1>.UseReflectionActivator()
        {
            UseReflectionActivator();
            return this;
        }

        #endregion

        #region Implementation of ITypeWhenSyntax

        /// <summary>
        /// Indicates that the binding should be used only for requests that support the specified condition.
        /// </summary>
        /// <param name="canResolveBindingDelegate">The specified <see cref="CanResolveBindingDelegate"/></param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax ITypeWhenSyntax.When(
            CanResolveBindingDelegate canResolveBindingDelegate)
        {
            When(canResolveBindingDelegate);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax ITypeWhenSyntax.WhenInto(Type type)
        {
            WhenInto(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax ITypeWhenSyntax.WhenInto<TType>()
        {
            WhenInto<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax ITypeWhenSyntax.WhenIntoIsAssignable(Type type)
        {
            WhenIntoIsAssignable(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax ITypeWhenSyntax.WhenIntoIsAssignable<TType>()
        {
            WhenIntoIsAssignable<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type when namespace equals.
        /// </summary>
        /// <param name="name">The name of namespace.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax ITypeWhenSyntax.WhenNamespaceEqual(string name)
        {
            WhenNamespaceEqual(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <param name="attributeType">The type of attribute.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax ITypeWhenSyntax.WhenClassHasAttribute(
            Type attributeType)
        {
            WhenClassHasAttribute(attributeType);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <typeparam name="T">The type of attribute.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax ITypeWhenSyntax.WhenClassHasAttribute<T>()
        {
            WhenClassHasAttribute<T>();
            return this;
        }

        #endregion

        #region Implementation of ITypeWhenSyntax<T1>

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax<T1> ITypeWhenSyntax<T1>.WhenInto(Type type)
        {
            WhenInto(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type will not be considered as valid target.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax<T1> ITypeWhenSyntax<T1>.WhenInto<TType>()
        {
            WhenInto<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <param name="type">The type of target.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax<T1> ITypeWhenSyntax<T1>.WhenIntoIsAssignable(Type type)
        {
            WhenIntoIsAssignable(type);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type <see cref="TType"/>.
        /// Types that derive from the specified type are considered as valid targets.
        /// </summary>
        /// <typeparam name="TType">The type of target.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax<T1> ITypeWhenSyntax<T1>.WhenIntoIsAssignable<TType>()
        {
            WhenIntoIsAssignable<TType>();
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for injections on the specified type when namespace equals.
        /// </summary>
        /// <param name="name">The name of namespace.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax<T1> ITypeWhenSyntax<T1>.WhenNamespaceEqual(string name)
        {
            WhenNamespaceEqual(name);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <param name="attributeType">The type of attribute.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax<T1> ITypeWhenSyntax<T1>.WhenClassHasAttribute(
            Type attributeType)
        {
            WhenClassHasAttribute(attributeType);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only for requests that support the specified condition.
        /// </summary>
        /// <param name="canResolveBindingDelegate">The specified <see cref="CanResolveBindingDelegate"/></param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax<T1> ITypeWhenSyntax<T1>.When(
            CanResolveBindingDelegate canResolveBindingDelegate)
        {
            When(canResolveBindingDelegate);
            return this;
        }

        /// <summary>
        /// Indicates that the binding should be used only when the class being injected has
        /// an attribute of the specified type.
        /// </summary>
        /// <typeparam name="TAttribute">The type of attribute.</typeparam>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackConstructorObjectPriorityScopeUseWithSyntax<T1> ITypeWhenSyntax<T1>.WhenClassHasAttribute<TAttribute>()
        {
            WhenClassHasAttribute<TAttribute>();
            return this;
        }

        #endregion

        #region Implementation of ITypeWithSyntax

        /// <summary>
        /// Use specified constructor argument.
        /// </summary>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="value">The specified parameter value.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeWithSyntax.WithConstructorArgument(string name, object value)
        {
            WithConstructorArgument(name, value);
            return this;
        }

        /// <summary>
        /// Use specified constructor argument.
        /// </summary>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeWithSyntax.WithConstructorArgument(string name,
                                                                                 ParameterDelegate<object>
                                                                                     parameterDelegate)
        {
            WithConstructorArgument(name, parameterDelegate);
            return this;
        }


        /// <summary>
        /// Use specified method argument.
        /// </summary>
        /// <param name="methodName">The specified method name.</param>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="value">The specified parameter value.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeWithSyntax.WithMethodArgument(string methodName, string name, object value)
        {
            WithMethodArgument(methodName, name, value);
            return this;
        }

        /// <summary>
        /// Use specified method argument.
        /// </summary>
        /// <param name="methodName"></param>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeWithSyntax.WithMethodArgument(string methodName, string name,
                                                                            ParameterDelegate<object> parameterDelegate)
        {
            WithMethodArgument(methodName, name, parameterDelegate);
            return this;
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="name">The specified property name.</param>
        /// <param name="value">The specified property value.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeWithSyntax.WithPropertyValue(string name, object value)
        {
            WithPropertyValue(name, value);
            return this;
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="name">The specified property name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeWithSyntax.WithPropertyValue(string name,
                                                                           ParameterDelegate<object> parameterDelegate)
        {
            WithPropertyValue(name, parameterDelegate);
            return this;
        }

        /// <summary>
        /// Use specified custom argument.
        /// </summary>
        /// <param name="parameter">The specified <see cref="IInjectionParameter"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax ITypeWithSyntax.WithParameter(IInjectionParameter parameter)
        {
            WithParameter(parameter);
            return this;
        }

        #endregion

        #region Implementation of IMethodWithSyntax<T1>

#if NOEXPRESSION
        /// <summary>
        /// Use specified constructor argument.
        /// </summary>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="value">The specified parameter value.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodWithSyntax<T1>.WithConstructorArgument(string name, object value)
        {
            WithConstructorArgument(name, value);
            return this;
        }

        /// <summary>
        /// Use specified constructor argument.
        /// </summary>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodWithSyntax<T1>.WithConstructorArgument(string name, ParameterDelegate<object> parameterDelegate)
        {
            WithConstructorArgument(name, parameterDelegate);
            return this;
        }

        /// <summary>
        /// Use specified method argument.
        /// </summary>
        /// <param name="methodName">The specified method name.</param>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="value">The specified parameter value.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodWithSyntax<T1>.WithMethodArgument(string methodName, string name, object value)
        {
            WithMethodArgument(methodName, name, value);
            return this;
        }

        /// <summary>
        /// Use specified method argument.
        /// </summary>
        /// <param name="methodName"></param>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodWithSyntax<T1>.WithMethodArgument(string methodName, string name, ParameterDelegate<object> parameterDelegate)
        {
            WithMethodArgument(methodName, name, parameterDelegate);
            return this;
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="name">The specified property name.</param>
        /// <param name="value">The specified property value.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodWithSyntax<T1>.WithPropertyValue(string name, object value)
        {
            WithPropertyValue(name, value);
            return this;
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="name">The specified property name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodWithSyntax<T1>.WithPropertyValue(string name, ParameterDelegate<object> parameterDelegate)
        {
            WithPropertyValue(name, parameterDelegate);
            return this;
        }

#else
        /// <summary>
        /// Use specified method arguments.
        /// </summary>
        /// <param name="constructorCall">The specified new instance expression.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax<T1> WithConstructorArguments(Expression<Func<ResolveContext, T1>> constructorCall)
        {
            using (_configurator.BeginConfigure)
            {
                Validate.ArgumentNotNull(constructorCall, "constructorCall");
                ConstructorInfo constructorInfo;
                var injectionParameters = InjectorUtilsInternal.ParseNewExpression(constructorCall, out constructorInfo);
                foreach (var injectionParameter in injectionParameters)
                {
                    _configurator.AddParameter(injectionParameter);
                }
                return this;
            }
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="property">The property accesss expression.</param>
        /// <param name="value">The specified property value.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax<T1> WithPropertyValue<TValue>(Expression<Func<T1, TValue>> property, TValue value)
        {
            using (_configurator.BeginConfigure)
            {
                PropertyInfo propertyInfo = InjectorUtilsInternal.GetProperty(property);
                Validate.IsAssignable(propertyInfo.PropertyType, value);
                _configurator.AddParameter(new PropertyParameter(propertyInfo.Name, propertyInfo.PropertyType, value));
                return this;
            }
        }

        /// <summary>
        /// Use specified method arguments.
        /// </summary>
        /// <param name="methodCall">The specified method call expression.</param>
        /// <returns>The fluent syntax.</returns>
        public IMethodCallbackObjectUseWithSyntax<T1> WithMethodArguments(Expression<Action<ResolveContext, T1>> methodCall)
        {
            Validate.ArgumentNotNull(methodCall, "methodCall");
            using (_configurator.BeginConfigure)
            {
                var parameters = InjectorUtilsInternal.ParseMethodExpression(methodCall);
                foreach (var injectionParameter in parameters)
                    _configurator.AddParameter(injectionParameter);
                return this;
            }
        }
#endif
        /// <summary>
        /// Use specified custom argument.
        /// </summary>
        /// <param name="parameter">The specified <see cref="IInjectionParameter"/>.</param>
        /// <returns>The fluent syntax.</returns>
        IMethodCallbackObjectUseWithSyntax<T1> IMethodWithSyntax<T1>.WithParameter(IInjectionParameter parameter)
        {
            WithParameter(parameter);
            return this;
        }

        #endregion

        #region Implementation of ITypeWithSyntax<T1>

#if NOEXPRESSION
        /// <summary>
        /// Use specified constructor argument.
        /// </summary>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="value">The specified parameter value.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithConstructorArgument(string name, object value)
        {
            WithConstructorArgument(name, value);
            return this;
        }

        /// <summary>
        /// Use specified constructor argument.
        /// </summary>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithConstructorArgument(string name, ParameterDelegate<object> parameterDelegate)
        {
            WithConstructorArgument(name, parameterDelegate);
            return this;
        }

        /// <summary>
        /// Use specified method argument.
        /// </summary>
        /// <param name="methodName">The specified method name.</param>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="value">The specified parameter value.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithMethodArgument(string methodName, string name, object value)
        {
            WithMethodArgument(methodName, name, value);
            return this;
        }

        /// <summary>
        /// Use specified method argument.
        /// </summary>
        /// <param name="methodName"></param>
        /// <param name="name">The specified parameter name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithMethodArgument(string methodName, string name, ParameterDelegate<object> parameterDelegate)
        {
            WithMethodArgument(methodName, name, parameterDelegate);
            return this;
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="name">The specified property name.</param>
        /// <param name="value">The specified property value.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithPropertyValue(string name, object value)
        {
            WithPropertyValue(name, value);
            return this;
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="name">The specified property name.</param>
        /// <param name="parameterDelegate">The specified <see cref="ParameterDelegate{T}"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithPropertyValue(string name, ParameterDelegate<object> parameterDelegate)
        {
            WithPropertyValue(name, parameterDelegate);
            return this;
        }
#else
        /// <summary>
        /// Use specified method arguments.
        /// </summary>
        /// <param name="constructorCall">The specified new instance expression.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithConstructorArguments(Expression<Func<ResolveContext, T1>> constructorCall)
        {
            WithConstructorArguments(constructorCall);
            return this;
        }

        /// <summary>
        /// Use specified propety argument.
        /// </summary>
        /// <param name="property">The property accesss expression.</param>
        /// <param name="value">The specified property value.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithPropertyValue<TValue>(Expression<Func<T1, TValue>> property, TValue value)
        {
            WithPropertyValue(property, value);
            return this;
        }

        /// <summary>
        /// Use specified method arguments.
        /// </summary>
        /// <param name="methodCall">The specified method call expression.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithMethodArguments(Expression<Action<ResolveContext, T1>> methodCall)
        {
            WithMethodArguments(methodCall);
            return this;
        }
#endif

        /// <summary>
        /// Use specified custom argument.
        /// </summary>
        /// <param name="parameter">The specified <see cref="IInjectionParameter"/>.</param>
        /// <returns>The fluent syntax.</returns>
        ITypeCallbackObjectUseWithSyntax<T1> ITypeWithSyntax<T1>.WithParameter(IInjectionParameter parameter)
        {
            WithParameter(parameter);
            return this;
        }
        #endregion
    }
}